home *** CD-ROM | disk | FTP | other *** search
- /* $Id: chpl.c,v 1.4 1996/02/19 15:55:53 jan Exp $
-
- Designed and implemented by Jan Wielemaker
- E-mail: jan@swi.psy.uva.nl
-
- Copyright (C) 1995 University of Amsterdam. All rights reserved.
- */
-
- #include "pl-incl.h"
- #include <stdio.h>
- #include <string.h>
- #include <stdarg.h>
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #ifdef HAVE_SYS_FILE_H
- #include <sys/file.h>
- #endif
- #include <stdlib.h>
- #include <sys/stat.h>
- #include <errno.h>
-
- #define closeFiles chplCloseFiles
- #define warning chplWarning
-
- #ifndef EOS
- #define EOS '\0'
- #endif
- #define MAXLINE 1024
- #ifndef MAXPATHLEN
- #define MAXPATHLEN 1024
- #endif
-
- #define ENDHEADER "# End Header\n"
-
- #define VERBOSE(g) if ( verbose ) { g; }
-
- static char *program;
- static char *state = NULL; /* program to work on */
- static char *emulator = NULL; /* -e */
- static char *outfile = NULL; /* -o */
- static char *headerfile = NULL; /* -h */
- static int verbose = 0; /* -v */
- static int extract = 0; /* -x */
-
- void
- warning(char *fm, ...)
- { va_list args;
-
- va_start(args, fm);
- fprintf(stderr, "%s: ", program);
- vfprintf(stderr, fm, args);
- fprintf(stderr, "\n");
- va_end(args);
- }
-
-
- void
- usage()
- { fprintf(stderr, "usage: %s -e emulator [-o outfile] state\n", program);
- fprintf(stderr, " or: %s -x [-o outfile] state\n", program);
- fprintf(stderr, " or: %s -h header [-o outfile] state\n", program);
-
- exit(1);
- }
-
-
- char *
- OsError(void)
- {
- #ifdef HAVE_STRERROR
- #ifdef __WIN32__
- return strerror(_xos_errno());
- #else
- return strerror(errno);
- #endif
- #else /*HAVE_STRERROR*/
- static char errmsg[64];
-
- #if unix
- extern int sys_nerr;
- #if !EMX
- extern char *sys_errlist[];
- #endif
- extern int errno;
-
- if ( errno < sys_nerr )
- return sys_errlist[errno];
- #endif
-
- sprintf(errmsg, "Unknown Error (%d)", errno);
- return errmsg;
- #endif /*HAVE_STRERROR*/
- }
-
-
- int
- replacevar(char *line, char *var, char *value)
- { char *s;
- int varl = strlen(var);
-
- for(s=line; *s; s++)
- { if ( *s == '$' && s[1] == '{' )
- { s += 2;
- if ( strncmp(s, var, varl) == 0 && s[varl] == '-' )
- { char *e;
-
- s += varl+1;
- if ( (e = strchr(s, '}')) )
- { char buf[MAXLINE];
-
- strcpy(buf, e);
- strcpy(s, value);
- strcat(s, buf);
- return 1;
- }
- }
- }
- }
-
- return 0;
- }
-
-
- static int
- cpmode(char *from, char *to)
- { struct stat buf;
-
- if ( stat(from, &buf) == 0 )
- { return chmod(to, buf.st_mode);
- }
-
- return -1;
- }
-
-
- static int
- openFiles(char *qlf, char *outfile, char *tmpqlf, FILE **in, FILE **out)
- { strcpy(tmpqlf, ".");
- strcat(tmpqlf, outfile);
-
- if ( (*in = fopen(qlf, "rb")) == NULL )
- { warning("cannot open %s: %s", qlf, OsError());
- return 1;
- }
- if ( (*out = fopen(tmpqlf, "wb")) == NULL )
- { warning("cannot open %s: %s", tmpqlf, OsError());
- return 1;
- }
-
- return 0;
- }
-
- static int
- closeFiles(char *qlf, char *outfile, char *tmpqlf, FILE *in, FILE *out)
- { if ( ferror(in) )
- { warning("Error reading %s: %s\n", qlf, OsError());
- return 1;
- }
- if ( ferror(out) )
- { warning("Error writing %s: %s\n", tmpqlf, OsError());
- return 1;
- }
-
- fclose(in);
- fclose(out);
-
- if ( cpmode(qlf, tmpqlf) != 0 )
- warning("failed to copy mode from %s to %s: %s", qlf, tmpqlf, OsError());
-
- if ( rename(tmpqlf, outfile) )
- { warning("failed to rename %s into %s: %s", tmpqlf, qlf, OsError());
- return 1;
- }
-
- return 0;
- }
-
-
- static int
- copyFd(FILE *in, FILE *out, char *infile, char *outfile)
- { char line[MAXLINE];
-
- for(;;)
- { char *s;
- int n;
-
- for(s=line, n=0; n<sizeof(line); n++)
- { int c = fgetc(in);
-
- if ( c == EOF )
- { char *q = line;
-
- for( ; q<s; q++)
- { if ( fputc(*q, out) < 0 )
- { warning("write failed on %s: %s", outfile, OsError());
- return 1;
- }
- }
- return 0;
- } else
- *s++ = c;
- }
- for(s=line, n=0; n<sizeof(line); n++)
- { if ( fputc(*s++, out) < 0 )
- { warning("write failed on %s: %s", outfile, OsError());
- return 1;
- }
- }
- }
- }
-
-
- int
- changeEmulator(char *qlf, char *emulator, char *outfile)
- { char tmpqlf[MAXPATHLEN];
- char line[MAXLINE];
- FILE *in, *out;
- int n;
-
- if ( openFiles(qlf, outfile, tmpqlf, &in, &out) )
- return 1;
-
- for(n=0; n<100; n++)
- { if ( !fgets(line, sizeof(line), in) )
- { warning("%s: not a SWI-Prolog saved state", qlf);
- return 1;
- }
- if ( replacevar(line, "SWIPL", emulator) )
- { fputs(line, out);
- goto copy;
- }
- fputs(line, out);
- }
- warning("%s: not a SWI-Prolog saved state", qlf);
- return 1;
-
- copy:
- if ( copyFd(in, out, qlf, tmpqlf) )
- return 1;
-
- return closeFiles(qlf, outfile, tmpqlf, in, out);
- }
-
-
- int
- extractHeader(char *qlf, char *outfile)
- { FILE *in, *out;
- char line[MAXLINE];
-
- if ( (in = fopen(qlf, "rb")) == NULL )
- { warning("cannot open %s: %s", qlf, OsError());
- return 1;
- }
- if ( !outfile )
- out = stdout;
- else
- { if ( (out = fopen(outfile, "wb")) == NULL )
- { warning("cannot open %s: %s", outfile, OsError());
- return 1;
- }
- }
-
- for(;;)
- { if ( !fgets(line, sizeof(line), in) )
- { warning("%s: Could not find %s", qlf, ENDHEADER);
- return 1;
- }
-
- if ( strcmp(line, ENDHEADER) == 0 )
- break;
-
- if ( fputs(line, out) < 0 )
- { warning("write failed: %s\n", OsError());
- return 1;
- }
- }
-
- fflush(out);
- if ( outfile )
- fclose(out);
- fclose(in);
-
- return 0;
- }
-
-
- static int
- skipHeader(FILE *in, char *file)
- { char line[MAXLINE];
-
- for(;;)
- { if ( !fgets(line, sizeof(line), in) )
- { warning("%s: Could not find %s", file, ENDHEADER);
- return 1;
- }
- if ( strcmp(line, ENDHEADER) == 0 )
- break;
- }
-
- return 0;
- }
-
-
- int
- replaceHeader(char *qlf, char *headerfile, char *outfile)
- { char tmpqlf[MAXPATHLEN];
- FILE *in, *out, *hf;
-
- if ( openFiles(qlf, outfile, tmpqlf, &in, &out) )
- return 1;
-
- if ( strcmp(headerfile, "-") == 0 )
- hf = stdin;
- else if ( (hf = fopen(headerfile, "r")) == NULL )
- { warning("Failed to open %s: %s", headerfile, OsError());
- return 1;
- }
-
- if ( copyFd(hf, out, headerfile, tmpqlf) )
- return 1;
- fprintf(out, "%s", ENDHEADER);
- if ( skipHeader(in, qlf) ||
- copyFd(in, out, qlf, tmpqlf) )
- return 1;
-
- return closeFiles(qlf, outfile, tmpqlf, in, out);
- }
-
-
- char *
- baseName(char *path)
- { char *b;
-
- for(b=path; *path; path++)
- { if ( *path == '/' )
- b = &path[1];
- }
-
- return b;
- }
-
-
- int
- main(int argc, char **argv)
- { program = baseName(argv[0]);
-
- argc--; argv++;
- while(argc > 0 && argv[0][0] == '-')
- { char *opts = &argv[0][1];
-
- argc--; argv++;
- for(; *opts; opts++)
- { switch(*opts)
- { case 'e':
- if ( argc <= 0 )
- usage();
- emulator = argv[0];
- argc--; argv++;
- continue;
- case 'o':
- if ( argc <= 0 )
- usage();
- outfile = argv[0];
- argc--; argv++;
- continue;
- case 'x':
- extract++;
- continue;
- case 'h':
- if ( argc <= 0 )
- usage();
- headerfile = argv[0];
- argc--; argv++;
- case 'v':
- verbose++;
- continue;
- }
- }
- }
-
- if ( argc != 1 )
- usage();
- state = argv[0];
-
- if ( extract )
- { exit(extractHeader(state, outfile));
- }
-
- if ( !outfile )
- outfile = state;
-
- if ( headerfile )
- { exit(replaceHeader(state, headerfile, outfile));
- }
-
- if ( emulator )
- { if ( emulator[0] != '/' )
- { warning("Path to emulator must be absolute");
- exit(1);
- }
- if ( access(emulator, X_OK) != 0 )
- warning("%s: emulator is not executable: %s\n", emulator, OsError());
-
-
- exit(changeEmulator(state, emulator, outfile));
- }
-
- usage();
- return 1;
- }
-
-
-